﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using SysImaging = System.Windows.Media.Imaging;
using iNet.Tasks;

namespace iNet.Media.Imaging
{
	/// <summary>
	/// 常見格式的影像編碼工作。
	/// </summary>
	public abstract class BasicImageEncodeTask : ImageEncodeTask
	{
		#region 建構子
		/// <summary>
		/// 初始化新的 WicBasedImageEncodeTask 執行個體。
		/// </summary>
		/// <param name="encodingFormat">影像編碼格式。</param>
		/// <exception cref="ArgumentNullException">encodingFormat 為 Null (Visual Basic 為 Nothing)。</exception>
		internal BasicImageEncodeTask(IMediaFormat encodingFormat)
			: base(encodingFormat)
		{ }
		#endregion
		#region CreateCompatibleMetadata
		/// <summary>
		/// 建立與此媒體格式相容且可編輯的中繼資料。
		/// </summary>
		/// <param name="template">現有的中繼資料。</param>
		/// <returns>與此媒體格式相容的中繼資料。</returns>
		public override IMetadata CreateCompatibleMetadata(IMetadata template)
		{
			IImageMetadata metadata = (template as IImageMetadata);
			if (metadata == null)
				return new GenericImageMetadata();
			if (metadata.IsReadOnly)
				return new GenericImageMetadata(template, false);
			return metadata;
		}
		#endregion
		#region CreateEncoder
		/// <summary>
		/// 建立點陣圖編碼器。
		/// </summary>
		/// <returns>點陣圖編碼器。</returns>
		internal abstract SysImaging.BitmapEncoder CreateEncoder();
		#endregion
		#region Encode
		protected override bool Encode(TaskVersion version, MediaStorage destination, MediaEncodeRequests mediaEncodeReqs, ImageEncodeRequests imageEncodeReqs)
		{
			//編碼影像
			if ((imageEncodeReqs & Imaging.ImageEncodeRequests.EncodeImage) != 0)
			{
				//取得影像
				IImage image = this.EncodingImage;
				if (image == null)
					throw new InvalidOperationException();

				//編碼
				Stream stream;
				if (!this.GetMediaStorageStream(version, destination, 0, out stream))
					throw new MediaEncodeFailedException(MediaEncodeFailedReason.CannotAccessStream);
				try
				{
					if (this.DoAction(new Action(() =>
						{
							//建立編碼器
							SysImaging.BitmapEncoder encoder = this.CreateEncoder();

							//初始化編碼器
							this.InitializeEncoderOverride(encoder, image);

							//編碼影像
							encoder.Save(stream);
						}),
						Timeout.Infinite))
					{
						this.CommitToMediaStorage(version, destination, 0, stream);
					}
				}
				catch (TargetInvocationException ex)
				{
					throw new MediaEncodeFailedException(MediaEncodeFailedReason.Unknown, ex.InnerException);
				}
				finally
				{
					this.ReleaseMediaStorageStream(version, destination, stream);
				}
			}

			//編碼完成
			return true;
		}
		#endregion
		#region InitializeEncoderOverride
		/// <summary>
		/// 初始化點陣圖編碼器。
		/// </summary>
		/// <param name="encoder">點陣圖編碼器。</param>
		/// <param name="image">編碼的影像。</param>
		internal virtual void InitializeEncoderOverride(SysImaging.BitmapEncoder encoder, IImage image)
		{
			encoder.Frames.Add(SysImaging.BitmapFrame.Create(image.ToImageSource().GetAsBitmapSource()));
		}
		#endregion
	}
}
